package com.test.spirngsecurity.conf;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.spirngsecurity.tool.ResultInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

//@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    //解码器
    @Bean
    PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }
    //账号密码
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.inMemoryAuthentication()
                .withUser("admin").password("123").authorities("ADMIN","USER")
                .and()
                .withUser("sang").password("123").authorities("USER")
                .and()
                .withUser("root").password("123").authorities("ADMIN","DBA");
    }
    //自定义配置
    @Override
    protected void configure(HttpSecurity http)throws Exception{
        http.authorizeRequests()
                .antMatchers("/admin/**").hasAnyAuthority("ADMIN")
                .antMatchers("/user/**").access("hasAnyAuthority('ADMIN','USER')")
                .antMatchers("/db/**").access("hasAnyAuthority('ADMIN') and hasAnyAuthority('DBA')")
                .antMatchers("/index.html").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login_page.html")
                .loginProcessingUrl("/login")
                .successHandler(new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter out=resp.getWriter();
                out.write(JSONObject.toJSONString(ResultInfo.success("登陆成功!",200)));
                out.flush();
                out.close();
            }
        })
                .failureHandler(new AuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
            resp.setContentType("application/json;charset=utf-8");
            PrintWriter out=resp.getWriter();
            if(e instanceof BadCredentialsException){
                out.write(JSONObject.toJSONString(ResultInfo.failure("密码错误登陆失败!",401)));
            }
            else {
                out.write(JSONObject.toJSONString(ResultInfo.failure("未知原因登陆失败!",401)));
            }
            out.flush();
            out.close();
            }
        })
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/logout")
//                .logoutSuccessUrl("/index.html") //由于配置了loLogoutSuccessHandler,就不生效
                .clearAuthentication(true)
                .invalidateHttpSession(true)
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out=resp.getWriter();
                        out.write(JSONObject.toJSONString(ResultInfo.success("登出成功!",200)));
                        resp.sendRedirect("/index.html");
                        out.flush();
                        out.close();

                    }
                })
                .deleteCookies("JSESSIONID")
                .and()
                .csrf().disable();
    }
    @Override
    public void configure(WebSecurity web) {
        //将项目中静态资源路径开放出来
        web.ignoring().antMatchers("/config/**", "/css/**", "/fonts/**", "/img/**", "/js/**");
    }
}
